//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package project_dataview_api_serv

import (
	"context"

	"atomgit.com/openlinksaas-org/api-server/api_common"
	"atomgit.com/openlinksaas-org/api-server/dao"
	"atomgit.com/openlinksaas-org/api-server/dao/dataview_dao"
	"atomgit.com/openlinksaas-org/api-server/utils"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/notices/notices_dataview"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_dataview_api"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *ProjectDataViewApiImpl) CreateEdge(ctx context.Context, req *project_dataview_api.CreateEdgeRequest) (*project_dataview_api.CreateEdgeResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_dataview_api.CreateEdgeResponse{
			Code:   project_dataview_api.CreateEdgeResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_dataview_api.CreateEdgeResponse{
			Code:   project_dataview_api.CreateEdgeResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_dataview_api.CreateEdgeResponse{
			Code:   project_dataview_api.CreateEdgeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_dataview_api.CreateEdgeResponse{
			Code:   project_dataview_api.CreateEdgeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	viewItem, err := dataview_dao.ViewDao.Get(ctx, req.ProjectId, req.ViewId)
	if err != nil {
		return &project_dataview_api.CreateEdgeResponse{
			Code:   project_dataview_api.CreateEdgeResponse_CODE_NO_VIEW,
			ErrMsg: "数据视图不存在",
		}, nil
	}
	canUpdate := false
	for _, userId := range viewItem.ExtraUpdateUserIdList {
		if userId == sessionItem.UserId {
			canUpdate = true
		}
	}
	if !(canUpdate || viewItem.OwnerUserId == sessionItem.UserId || projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_dataview_api.CreateEdgeResponse{
			Code:   project_dataview_api.CreateEdgeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	exist, err := dataview_dao.NodeDao.Exist(ctx, req.ViewId, req.Edge.EdgeKey.FromNodeId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_dataview_api.CreateEdgeResponse{
			Code:   project_dataview_api.CreateEdgeResponse_CODE_NO_NODE,
			ErrMsg: "视图节点不存在",
		}, nil
	}
	exist, err = dataview_dao.NodeDao.Exist(ctx, req.ViewId, req.Edge.EdgeKey.ToNodeId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_dataview_api.CreateEdgeResponse{
			Code:   project_dataview_api.CreateEdgeResponse_CODE_NO_NODE,
			ErrMsg: "视图节点不存在",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = dataview_dao.EdgeDao.Insert(sessCtx, &dataview_dao.EdgeInfoDbItem{
			ViewId:       req.ViewId,
			FromNodeId:   req.Edge.EdgeKey.FromNodeId,
			FromHandleId: req.Edge.EdgeKey.FromHandleId,
			ToNodeId:     req.Edge.EdgeKey.ToNodeId,
			ToHandleId:   req.Edge.EdgeKey.ToHandleId,
			Label:        req.Edge.Label,
		})
		if err != nil {
			return nil, err
		}
		return &project_dataview_api.CreateEdgeResponse{
			Code: project_dataview_api.CreateEdgeResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_dataview.CreateEdgeNotice{
		ProjectId: req.ProjectId,
		ViewId:    req.ViewId,
		EdgeKey: &notices_dataview.EdgeKey{
			FromNodeId:   req.Edge.EdgeKey.FromNodeId,
			FromHandleId: req.Edge.EdgeKey.FromHandleId,
			ToNodeId:     req.Edge.EdgeKey.ToNodeId,
			ToHandleId:   req.Edge.EdgeKey.ToHandleId,
		},
	})
	return ret.(*project_dataview_api.CreateEdgeResponse), nil
}

func (apiImpl *ProjectDataViewApiImpl) UpdateEdge(ctx context.Context, req *project_dataview_api.UpdateEdgeRequest) (*project_dataview_api.UpdateEdgeResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_dataview_api.UpdateEdgeResponse{
			Code:   project_dataview_api.UpdateEdgeResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_dataview_api.UpdateEdgeResponse{
			Code:   project_dataview_api.UpdateEdgeResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_dataview_api.UpdateEdgeResponse{
			Code:   project_dataview_api.UpdateEdgeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_dataview_api.UpdateEdgeResponse{
			Code:   project_dataview_api.UpdateEdgeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	viewItem, err := dataview_dao.ViewDao.Get(ctx, req.ProjectId, req.ViewId)
	if err != nil {
		return &project_dataview_api.UpdateEdgeResponse{
			Code:   project_dataview_api.UpdateEdgeResponse_CODE_NO_VIEW,
			ErrMsg: "数据视图不存在",
		}, nil
	}

	exist, err := dataview_dao.EdgeDao.Exist(ctx, req.ViewId, req.Edge.EdgeKey)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_dataview_api.UpdateEdgeResponse{
			Code:   project_dataview_api.UpdateEdgeResponse_CODE_NO_EDGE,
			ErrMsg: "视图连接不存在",
		}, nil
	}

	canUpdate := false
	for _, userId := range viewItem.ExtraUpdateUserIdList {
		if userId == sessionItem.UserId {
			canUpdate = true
		}
	}
	if !(canUpdate || viewItem.OwnerUserId == sessionItem.UserId || projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_dataview_api.UpdateEdgeResponse{
			Code:   project_dataview_api.UpdateEdgeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = dataview_dao.EdgeDao.Update(sessCtx, req.ViewId, req.Edge.EdgeKey, req.Edge.Label)
		if err != nil {
			return nil, err
		}
		return &project_dataview_api.UpdateEdgeResponse{
			Code: project_dataview_api.UpdateEdgeResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_dataview.UpdateEdgeNotice{
		ProjectId: req.ProjectId,
		ViewId:    req.ViewId,
		EdgeKey: &notices_dataview.EdgeKey{
			FromNodeId:   req.Edge.EdgeKey.FromNodeId,
			FromHandleId: req.Edge.EdgeKey.FromHandleId,
			ToNodeId:     req.Edge.EdgeKey.ToNodeId,
			ToHandleId:   req.Edge.EdgeKey.ToHandleId,
		},
	})
	return ret.(*project_dataview_api.UpdateEdgeResponse), nil
}

func (apiImpl *ProjectDataViewApiImpl) RemoveEdge(ctx context.Context, req *project_dataview_api.RemoveEdgeRequest) (*project_dataview_api.RemoveEdgeResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_dataview_api.RemoveEdgeResponse{
			Code:   project_dataview_api.RemoveEdgeResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_dataview_api.RemoveEdgeResponse{
			Code:   project_dataview_api.RemoveEdgeResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_dataview_api.RemoveEdgeResponse{
			Code:   project_dataview_api.RemoveEdgeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_dataview_api.RemoveEdgeResponse{
			Code:   project_dataview_api.RemoveEdgeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	viewItem, err := dataview_dao.ViewDao.Get(ctx, req.ProjectId, req.ViewId)
	if err != nil {
		return &project_dataview_api.RemoveEdgeResponse{
			Code:   project_dataview_api.RemoveEdgeResponse_CODE_NO_VIEW,
			ErrMsg: "数据视图不存在",
		}, nil
	}

	exist, err := dataview_dao.EdgeDao.Exist(ctx, req.ViewId, req.EdgeKey)
	if err != nil {
		return nil, err
	}
	if !exist { //对象不存在
		return &project_dataview_api.RemoveEdgeResponse{
			Code: project_dataview_api.RemoveEdgeResponse_CODE_OK,
		}, nil
	}

	canUpdate := false
	for _, userId := range viewItem.ExtraUpdateUserIdList {
		if userId == sessionItem.UserId {
			canUpdate = true
		}
	}
	if !(canUpdate || viewItem.OwnerUserId == sessionItem.UserId || projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_dataview_api.RemoveEdgeResponse{
			Code:   project_dataview_api.RemoveEdgeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = dataview_dao.EdgeDao.Remove(sessCtx, req.ViewId, req.EdgeKey)
		if err != nil {
			return nil, err
		}
		return &project_dataview_api.RemoveEdgeResponse{
			Code: project_dataview_api.RemoveEdgeResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_dataview.RemoveEdgeNotice{
		ProjectId: req.ProjectId,
		ViewId:    req.ViewId,
		EdgeKey: &notices_dataview.EdgeKey{
			FromNodeId:   req.EdgeKey.FromNodeId,
			FromHandleId: req.EdgeKey.FromHandleId,
			ToNodeId:     req.EdgeKey.ToNodeId,
			ToHandleId:   req.EdgeKey.ToHandleId,
		},
	})
	return ret.(*project_dataview_api.RemoveEdgeResponse), nil
}

func (apiImpl *ProjectDataViewApiImpl) ListEdge(ctx context.Context, req *project_dataview_api.ListEdgeRequest) (*project_dataview_api.ListEdgeResponse, error) {
	emptyList := []*project_dataview_api.EdgeInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_dataview_api.ListEdgeResponse{
			Code:     project_dataview_api.ListEdgeResponse_CODE_WRONG_SESSION,
			ErrMsg:   "会话不存在",
			EdgeList: emptyList,
		}, nil
	}
	//检查权限
	_, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_dataview_api.ListEdgeResponse{
			Code:     project_dataview_api.ListEdgeResponse_CODE_NO_PROJECT,
			ErrMsg:   "项目不存在",
			EdgeList: emptyList,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_dataview_api.ListEdgeResponse{
			Code:     project_dataview_api.ListEdgeResponse_CODE_NO_PERMISSION,
			ErrMsg:   "没有权限",
			EdgeList: emptyList,
		}, nil
	} else if err != nil {
		return nil, err
	}

	exist, err := dataview_dao.ViewDao.Exist(ctx, req.ProjectId, req.ViewId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_dataview_api.ListEdgeResponse{
			Code:     project_dataview_api.ListEdgeResponse_CODE_NO_VIEW,
			ErrMsg:   "数据视图不存在",
			EdgeList: emptyList,
		}, nil
	}

	edgeItemList, err := dataview_dao.EdgeDao.List(ctx, req.ViewId)
	if err != nil {
		return nil, err
	}
	edgeList := []*project_dataview_api.EdgeInfo{}
	for _, edgeItem := range edgeItemList {
		edgeList = append(edgeList, edgeItem.ToEdgeInfo())
	}
	return &project_dataview_api.ListEdgeResponse{
		Code:     project_dataview_api.ListEdgeResponse_CODE_OK,
		EdgeList: edgeList,
	}, nil
}

func (apiImpl *ProjectDataViewApiImpl) GetEdge(ctx context.Context, req *project_dataview_api.GetEdgeRequest) (*project_dataview_api.GetEdgeResponse, error) {
	emptyInfo := &project_dataview_api.EdgeInfo{
		EdgeKey: &project_dataview_api.EdgeInfoKey{},
	}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_dataview_api.GetEdgeResponse{
			Code:   project_dataview_api.GetEdgeResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
			Edge:   emptyInfo,
		}, nil
	}
	//检查权限
	_, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_dataview_api.GetEdgeResponse{
			Code:   project_dataview_api.GetEdgeResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
			Edge:   emptyInfo,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_dataview_api.GetEdgeResponse{
			Code:   project_dataview_api.GetEdgeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
			Edge:   emptyInfo,
		}, nil
	} else if err != nil {
		return nil, err
	}

	exist, err := dataview_dao.ViewDao.Exist(ctx, req.ProjectId, req.ViewId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_dataview_api.GetEdgeResponse{
			Code:   project_dataview_api.GetEdgeResponse_CODE_NO_VIEW,
			ErrMsg: "数据视图不存在",
			Edge:   emptyInfo,
		}, nil
	}
	edgeItem, err := dataview_dao.EdgeDao.Get(ctx, req.ViewId, req.EdgeKey)
	if err != nil {
		return &project_dataview_api.GetEdgeResponse{
			Code:   project_dataview_api.GetEdgeResponse_CODE_NO_EDGE,
			ErrMsg: "视图连接不存在",
			Edge:   emptyInfo,
		}, nil
	}

	return &project_dataview_api.GetEdgeResponse{
		Code: project_dataview_api.GetEdgeResponse_CODE_OK,
		Edge: edgeItem.ToEdgeInfo(),
	}, nil
}
